from . import models
from course.models import Course
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from lib.iPay import alipay, gateway
import uuid
from django.conf import settings


# 这个序列化类只用来做反序列化
class PaySerializer(serializers.ModelSerializer):
    # courses 不是表的字段，重写
    # 前端传入的是[1,2]---》[id为1的课程对象，id为2的课程对象]
    # 把id，id的列表，映射成对象或对象列表，是queryset指定的对象
    courses = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), many=True)

    # 使用下面方式，courses得到的还是课程列表，后期通过课程列表再做查询，查成课程对象列表
    # courses = serializers.ListField()

    class Meta:
        model = models.Order
        # {subject:'xx课程',total_amount:99,pay_type:1,courses:[1,2]}
        fields = ['subject', 'total_amount', 'pay_type', 'courses']
        extra_kwargs = {
            'subject': {'required': True},
            'total_amount': {'required': True}
        }

    def _check_total_amount(self, attrs):
        # 取出总价格，取出所有课程累加，比较俩值
        total_amount = attrs.get('total_amount')
        real_amount = 0
        for course in attrs.get('courses'):
            real_amount += course.price
        if not total_amount == real_amount:
            raise ValidationError({'detail':'价格不合法'})

    def _get_user(self):
        # 从request.user中获取
        # 在序列化类中取不到request对象,在视图类中初始化序列化类的时候self.get_serializer(data=request.data,context={'request':request})
        return self.context['request'].user

    def _get_out_trade_no(self):

        return str(uuid.uuid4()).replace('-','')

    def _get_pay_url(self, attrs, out_trade_no):
        # 导入自定义的包中alipay对象，调用对象的api_alipay_trade_page_pay方法
        res = alipay.api_alipay_trade_page_pay(
            subject=attrs.get('subject'),
            total_amount=float(attrs.get('total_amount')),  # 坑，必须是float类型
            out_trade_no=out_trade_no,
            # 放到配置文件
            return_url=settings.RETURN_URL,  # get回调，掉前端，显示支付成功，用户可以看到
            # return_url="http://www.baidu.com",  # get回调，掉前端，显示支付成功，用户可以看到
            notify_url=settings.NOTIFY_URL,  # post回调，掉后端，修改订单状态
        )
        return gateway + res

    def _before_create(self, attrs, user, out_trade_no, pay_url):

        # 把user，放到attrs中
        attrs['user'] = user
        # 把订单号，放到attrs中
        attrs['out_trade_no'] = out_trade_no
        # 把支付连接放到context中
        self.context['pay_url'] = pay_url

    def validate(self, attrs):
        '''
        1 校验价格是否合法，不合法抛异常
        2 获取当前登录用户，从request中获取
        3 生成不重复的订单号，uuid生成
        4 生成支付连接，支付宝支付的包
        5 入库前准备，把user放入attrs中，把支付连接放到self.context中
        '''

        self._check_total_amount(attrs)
        user = self._get_user()
        out_trade_no = self._get_out_trade_no()
        pay_url = self._get_pay_url(attrs, out_trade_no)
        self._before_create(attrs, user, out_trade_no, pay_url)  # 需要参数

        return attrs

    # 重写，因为存了两个表
    def create(self, validated_data):
        courses = validated_data.pop('courses')
        # 存订单表
        order = models.Order.objects.create(**validated_data)
        # 存订单详情表
        for course in courses:
            models.OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)

        return order
